package com.qf.fmall2203.category.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qf.fmall2203.category.entity.Category;
import com.qf.fmall2203.category.mapper.CategoryMapper;
import com.qf.fmall2203.category.service.ICategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.fmall2203.product.entity.Product;
import com.qf.fmall2203.product.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品分类 服务实现类
 * </p>
 *
 * @author dongjl
 * @since 2023-02-14
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Autowired
    IProductService productService;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<Category> categoryListRecursiveBetter() {

        // 查询全表的分类信息
        final List<Category> all = list();

        // 构建一个Map ，key=parentId， value=List<Catetgory>
//        final Map<Integer, List<Category>> map = all.stream().collect(Collectors.groupingBy(category -> {
//            // 按照 parentId进行分组
//            return category.getParentId();
//        }));

        final Map<Integer, List<Category>> pIdMap = all.stream().collect(Collectors.groupingBy(Category::getParentId));


        // 获取顶级分类List
        final List<Category> first = pIdMap.get(0);

        // 给当前分类List填充下级分类数据
        pupulateBetter(first,pIdMap);

//        pIdMap.forEach(new BiConsumer<Integer, List<Category>>() {
//            @Override
//            public void accept(Integer key, List<Category> value) {
//                System.out.println(key);
//                value.forEach(System.out::println);
//            }
//        });


        return first;
    }

    private void pupulateBetter(List<Category> list, Map<Integer, List<Category>> pIdMap) {

        for (Category category : list) {

            final Integer cId = category.getCategoryId();

            // 获取当前cId下属分类信息
            final List<Category> child = pIdMap.get(cId);

            if (child!=null&&child.size()>0){
                pupulateBetter(child,pIdMap);
                // 填充下属分类
                category.setCategories(child);
            }else {
                // 当没有下级分类数据时，创建一个长度为0的list，避免遍历数据时出现空指针异常；也确保前端拿到的json中，是[]
                category.setCategories(new ArrayList<>());
            }


        }


    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<Category> categoryListRecursive() {

        // 查询全表的分类信息
        final List<Category> all = list();

        // 通过stream 的filter方法，获取到 顶级分类数据
        final List<Category> firstList = all.stream().filter(category -> category.getParentId().equals(0)).collect(Collectors.toList());


        // 给当前的分类信息填充下级分类信息
        populateChild(firstList,all);


//        firstList.forEach(System.out::println);

        return firstList;
    }

    /**
     * 给传入的 list中的所有分类对象填充下级分类
     * @param list  传入的分类的list
     * @param all   全部分类数据
     */
    private void populateChild(List<Category> list, List<Category> all) {

        // 给 当前分类list中的所有分类对象填充下属的分类信息
        for (Category category : list) {
            final Integer categoryId = category.getCategoryId();
            // 过滤all，保留 parentId= categoryId 的数据，就是当前需要的下级分类数据
            final List<Category> child = all.stream().filter(c -> c.getParentId().equals(categoryId)).collect(Collectors.toList());

            if (child!=null&&child.size()>0){
                populateChild(child,all);
            }

            // 挂载下级分类
            category.setCategories(child);
        }
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<Category> categoryList() {

        // 查询所有一级分类信息
        final List<Category> firstCategoryList = list(new QueryWrapper<Category>().eq("parent_id", 0));

        // 遍历所有查询到的一级分类，填充二级分类数据
        for (Category category : firstCategoryList) {

            // 获取当前一级分类ID
            final Integer categoryId = category.getCategoryId();

            // 查询当前ID下有哪些二级分类
            final List<Category> secondCateoryList = list(new QueryWrapper<Category>().eq("parent_id", categoryId));

            // 遍历 secondCateoryList ，为每个二级分类对象填充 三级分类 数据
            for (Category sec : secondCateoryList) {
                // 获取二级分类ID
                final Integer secId = sec.getCategoryId();
                final List<Category> thirdCategoryList = list(new QueryWrapper<Category>().eq("parent_id", secId));

                // 把三级分类信息设置到二级分类对象中
                sec.setCategories(thirdCategoryList);
            }

            // 把查询出来的二级分类，设置到一级分类对象中
            category.setCategories(secondCateoryList);

        }

        return firstCategoryList;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<Category> categoryListBySql() {

        final CategoryMapper mapper = this.getBaseMapper();

        return mapper.listCategoryList();

    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<Category> categoryRecommends() {

        //1. 查顶级分类信息
        final List<Category> firstCategory = list(new QueryWrapper<Category>().eq("parent_id", 0));

        //2. 把需要使用到的商品信息一次性查询出来
        //2.1 List<Category> ---> List<CategoryID>
        final List<Integer> categoryIDList = firstCategory.stream().map(Category::getCategoryId).collect(Collectors.toList());

        //2.2 查询商品信息
        final List<Product> productList = productService.list(new QueryWrapper<Product>().in("root_category_id", categoryIDList));

        //3. 把productList中的商品图片信息填充上
        productService.populateImg(productList);

        //4. List<Product>  ----->  Map<RootCategoryID, List<Product> >
        final Map<Integer, List<Product>> map = productList.stream().collect(Collectors.groupingBy(Product::getRootCategoryId));

        // 获取map中的key
        final Set<Integer> categoryIdSet = map.keySet();

        // 过滤数据，把不包含商品的 分类信息排除掉
        final List<Category> firstCategoryList = firstCategory.stream().filter(c -> categoryIdSet.contains(c.getCategoryId())).collect(Collectors.toList());

        //5. 把商品信息挂到 catetory对象中
        for (Category category : firstCategoryList) {
            final Integer categoryId = category.getCategoryId();
            final List<Product> products = map.get(categoryId);
            // 把products按照销量倒叙，取前6个
            final List<Product> sortedProductList = products.stream().sorted((o1, o2) -> o2.getSoldNum() - o1.getSoldNum()).limit(6).collect(Collectors.toList());
            category.setProducts(sortedProductList);
        }

        return firstCategoryList;
    }
}
